//
//  ST_MinePlayerView.swift
//  btvideo
//
//  Created by DC on 2022/6/22.
//  Copyright © 2022 JarvanZhang. All rights reserved.
//

import UIKit
import SwiftyJSON
import AVFoundation

class ST_MinePlayerView: UIView {

    var isPlaying = false
    var isStop = false
    var isBig = false
    var readyToPlay = false
    var lastFrame = CGRect(x: ScreenWidth - 113, y: statusBarHeight + 15 + 23, width: 113, height: 163)
    var lastCorner: CAShapeLayer?
    
    var playerObserverArray: Array<(Object: NSObject, Key: String)> = [] //储存绑定KVO的数组
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        isHidden = true
        
        make_u_i()
        bind()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        playerLayer.frame = playerView.bounds
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        if newSuperview == nil {
            playerRemoveObserver()
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &playbackLikelyToKeepUpContext {
            if player.currentItem!.isPlaybackLikelyToKeepUp {
                readyToPlay = true
                isHidden = false
            }
        }
    }
    
    private lazy var rightCorner: CAShapeLayer = {
        let maskPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 113, height: 163), byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: 16, height: 16))
        
        let v = CAShapeLayer()
        v.frame = CGRect(x: 0, y: 0, width: 113, height: 163)
        v.path = maskPath.cgPath
        return v
    }()
    
    private lazy var leftCorner: CAShapeLayer = {
        let maskPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 113, height: 163), byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width: 16, height: 16))
        
        let v = CAShapeLayer()
        v.frame = CGRect(x: 0, y: 0, width: 113, height: 163)
        v.path = maskPath.cgPath
        return v
    }()
    
    private lazy var allCorner: CAShapeLayer = {
        let maskPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 113, height: 163), byRoundingCorners: [.topRight, .bottomRight, .topLeft, .bottomLeft], cornerRadii: CGSize(width: 16, height: 16))
        
        let v = CAShapeLayer()
        v.frame = CGRect(x: 0, y: 0, width: 113, height: 163)
        v.path = maskPath.cgPath
        return v
    }()
    
    private lazy var playerView: UIView = {
        let v = UIView()
        v.backgroundColor = .clear
        v.cornerRadius = 12
        return v
    }()
    
    private var playbackLikelyToKeepUpContext = 0
    private lazy var player = AVPlayer()
    private lazy var playerLayer: AVPlayerLayer = {
        let v = AVPlayerLayer(player: player)
        v.videoGravity = .resizeAspectFill
        return v
    }()
    
    private lazy var tap: UITapGestureRecognizer = {
        let v = UITapGestureRecognizer()
        return v
    }()
    
    private lazy var close_button: UIButton = {
        let v = UIButton()
        v.setImageForAllStates(ST_ImageUtils.imageName("personal_video_close")!)
        v.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        return v
    }()
    
    private lazy var pan: UIPanGestureRecognizer = {
        let v = UIPanGestureRecognizer()
        v.addTarget(self, action: #selector(panScene))
        return v
    }()
}

private extension ST_MinePlayerView {
    
    func make_u_i() {
        layer.mask = rightCorner
        lastCorner = rightCorner
        
        addSubview(playerView)
        playerView.layer.addSublayer(playerLayer)
        
        playerView.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 6, left: 6, bottom: 6, right: 6))
        }
        
        addGestureRecognizer(tap)
        addGestureRecognizer(pan)
        
        addSubview(close_button)
        close_button.snp.makeConstraints { make in
            make.right.equalToSuperview().offset(5)
            make.top.equalToSuperview().offset(-5)
            make.size.equalTo(CGSize(width: 48, height: 48))
        }
    }
    
    func bind() {
        tap.rx.event.withUnretained(self).subscribe(onNext: { own, _ in
            if own.isPlaying == false {
                return
            }
            
            UIView.animate(withDuration: 0.25) {
                if own.isBig == false {
                    own.isBig = true
                    own.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight)
                    own.backgroundColor = .black
                    own.layer.mask = nil
                    own.playerLayer.videoGravity = .resizeAspect
                    own.close_button.alpha = 0
                }else {
                    own.isBig = false
                    own.frame = own.lastFrame
                    own.backgroundColor = .white
                    own.layer.mask = own.lastCorner
                    own.playerLayer.videoGravity = .resizeAspectFill
                    own.close_button.alpha = 1
                }
                
                own.layoutIfNeeded()
                own.layoutSubviews()
            }
        }).disposed(by: rx.disposeBag)
        
        NotificationCenter.default.rx.notification(.AVPlayerItemDidPlayToEndTime, object: nil).withUnretained(self).subscribe(onNext: { own, _ in
            if own.isPlaying == false {
                return
            }
            
            own.player.seek(to: CMTime.zero)
            own.player.play()
            own.isPlaying = true
        }).disposed(by: rx.disposeBag)
        
        playerAddObserver()
        
        NotificationCenter.default.rx.notification(.personalVideoNeedPause).subscribe(onNext: { [weak self] _ in
            self?.pause()
        }).disposed(by: rx.disposeBag)
        
        NotificationCenter.default.rx.notification(.personalVideoNeedPlay).subscribe(onNext: { [weak self] _ in
            self?.play()
        }).disposed(by: rx.disposeBag)

        close_button.rx.tap.withUnretained(self).subscribe(onNext: { own, _ in
            own.isHidden = true
            own.player.pause()
            own.isPlaying = false
            own.isStop = true
        }).disposed(by: rx.disposeBag)
    }
    
    @objc func panScene(_ pan: UIPanGestureRecognizer) {
        guard let view = pan.view else {
            return
        }
        let center = pan.location(in: view.superview)
        
        switch pan.state {
        case .began:
            layer.mask = allCorner
            lastCorner = allCorner
        case .changed:
            view.center = center
        case .ended:
            var x = 0.cgFloat
            var y = 0.cgFloat
            if center.x >= (ScreenWidth / 2) {
                x = ScreenWidth - 113
                layer.mask = rightCorner
                lastCorner = rightCorner
            }else {
                x = 0
                layer.mask = leftCorner
                lastCorner = leftCorner
            }
            if center.y - 81.5  < statusBarHeight + 15 + 23 {
                y = statusBarHeight + 15 + 23
            }else if center.y + 81.5 > ScreenHeight - BTSafeAreaBottom {
                y = ScreenHeight - BTSafeAreaBottom - 163
            }else {
                y = center.y - 81.5
            }
            lastFrame = CGRect(x: x, y: y, width: 113, height: 163)
            
            UIView.animate(withDuration: 0.25) {
                self.frame = self.lastFrame
            }
        default:
            break
        }
    }
    
    func playerAddObserver() {
        player.addObserver(self, forKeyPath: "currentItem.playbackLikelyToKeepUp", options: .new, context: &playbackLikelyToKeepUpContext)
        let tuple = (Object: player, Key: "currentItem.playbackLikelyToKeepUp")
        playerObserverArray.append(tuple)
    }
    
    func playerRemoveObserver() {
        guard let index = playerObserverArray.firstIndex(where: { $0.Object == player && $0.Key == "currentItem.playbackLikelyToKeepUp" }) else {
            return
        }
        player.removeObserver(self, forKeyPath: "currentItem.playbackLikelyToKeepUp")
        playerObserverArray.remove(at: index)
    }
}

extension ST_MinePlayerView {
    
    func bind(data: JSON) {
        if data["video_url"].stringValue.count > 0, let url = URL(string: data["video_url"].stringValue) {
            player.replaceCurrentItem(with: AVPlayerItem(url: url))
            player.play()
            isPlaying = true
            isStop = false
        }else {
            isHidden = true
            isStop = true
        }
    }
    
    func addSentMessage() {
        guard let vc = self.parentViewController else {
            return
        }
        
        vc.rx.sentMessage(#selector(vc.viewDidAppear(_:))).withUnretained(self).subscribe(onNext: { own, _ in
            own.play()
        }).disposed(by: rx.disposeBag)
        
        vc.rx.sentMessage(#selector(vc.viewWillDisappear(_:))).withUnretained(self).subscribe(onNext: { own, _ in
            own.pause()
        }).disposed(by: rx.disposeBag)
    }
    
    func play() {
        if readyToPlay == false {
            return
        }
        
        if isStop || isPlaying {
            return
        }
        
        guard let vc = self.parentViewController as? ST_PairsCenterViewController else {
            return
        }
        if vc.headerView.pairsHeader?.playing ?? false == true || vc.headerView.voiceSignControl?.isPlaying ?? false == true {
            return
        }
        
        player.play()
        isPlaying = true
    }
    
    func pause() {
        if isStop || !isPlaying {
            return
        }
        player.pause()
        isPlaying = false
    }
    
}
